﻿using System;
using System.Collections.Generic;
using System.Text;

using ELW.Library.Math;
using ELW.Library.Math.Exceptions;
using ELW.Library.Math.Expressions;
using ELW.Library.Math.Tools;

namespace Simulator
{
    /// <summary>
    /// Степени равенства в логическом выражении
    /// </summary>
    [Serializable]
    public enum Equality
    {
        less,
        less_or_equal,
        equal,
        more_or_equal,
        more
    }
    /// <summary>
    /// Блок решения
    /// </summary>
    [Serializable]
    public class Decision: Block
    {
        /// <summary>
        /// 3 указателя на следующие блоки, 1 из которых всегда null
        /// </summary>
        public new Block[] Next { get; set; }

        /// <summary>
        /// Список из 3 символов, соответствующих состоянию выходных портов ("Top", "Middle", "Bottom").
        /// 't' - выход по true, 'f' - выход по false, 'h' - скрытый выход
        /// </summary>
        public List<char> PortMap { get; set; }

        private string Cstr;
        public CompiledExpression CompareCompiledString;

        /// <summary>
        /// Получить или установить выражение для сравнения
        /// </summary>
        public string CompareString
        {
            get
            { return Cstr; }
            set
            {
                Cstr = value;
                PreparedExpression preparedExpression = ToolsHelper.Parser.Parse(Cstr);
                CompareCompiledString = ToolsHelper.Compiler.Compile(preparedExpression);
            }
        }
        /// <summary>
        /// При попадании сущности в этот блок сущность направляется по одному из
        /// выходов в соответствии со значением качества
        /// </summary>
        /// <param name="e">Сущность</param>
        public override void PutEntity(ref Entity e)
        {
            bool logical = false;

            List<VariableValue> variables = new List<VariableValue>();
            //добавим переменные по качеству и сложности
            double C = e.Complexity ;
            variables.Add(new VariableValue(C, "C"));

            double Q = e.Quality;
            variables.Add(new VariableValue(Q, "Q"));

            double cmp = ToolsHelper.Calculator.Calculate(CompareCompiledString, variables);

            if (cmp != 0)
                logical = true;
            //пройдемся по портам, передадим в тот, в который надо
            for (int i = 0; i < 3; i++)
            {
                if (((PortMap[i] == 't') && (logical)) || ((PortMap[i] == 'f') && (!logical)))
                {
                    Next[i].PutEntity(ref e);
                    break;
                }
                
            }
        }
        public Decision()
        {
            //примем настройки портов по умолчанию
            PortMap = new List<char>();
            PortMap.Add('t');
            PortMap.Add('f');
            PortMap.Add('h');
            Next = new Block[3];
            for (int i = 0; i < 3; i++)
            {
                Next[i] = null;
            }
            CompareString = "С > 0";
        }

        public override void ClearEntities()
        {
            
            //do nothing
        }
    }
}
